import axios from 'axios';
// axios 提供的类型
import type { AxiosInstance, AxiosRequestConfig } from 'axios';
import type { requestIntercepors, requestConfig } from './type';

// 返回数据延迟时间
const delay = () => {
	return new Promise(resolve => {
		setTimeout(() => {
			resolve('延迟函数执行完毕');
		}, Number(import.meta.env.VITE_DELAY));
	});
};

class request {
	// 保存axios实例的参数
	instance: AxiosInstance;
	interceptors?: requestIntercepors;

	// 构造器：每次new 都会重新创建一个实例
	constructor(config: requestConfig) {
		// 创建的axios实例赋值给 instance
		this.instance = axios.create(config);
		// 单实例传递参数
		this.interceptors = config.interceptors;

		// 执行顺序：单请求 => 所有请求 => 单响应 => 所有响应

		// 单个实例的请求拦截器
		this.instance.interceptors.request.use(this.interceptors?.requestIntercepor, this.interceptors?.requestInterceporCatch);
		// 单个实例的响应拦截器
		this.instance.interceptors.response.use(this.interceptors?.responseIntercepor, this.interceptors?.responseInterceporCatch);

		// 所有实例的请求拦截器
		this.instance.interceptors.request.use(
			config => {
				// console.log(config, "所有实例请求成功拦截");
				return config;
			},
			err => {
				console.log(err, '所有实例请求失败拦截');
				return new Promise((resolve, reject) => reject(err));
			}
		);
		// 所有实例的响应拦截器
		this.instance.interceptors.response.use(
			async res => {
				await delay();
				// console.log(res, "所有实例响应成功拦截");
				return res;
			},
			async err => {
				console.log(err, '所有实例响应失败拦截');
				await delay();
				return new Promise((resolve, reject) => reject(err));
			}
		);
	}

	// 发送网络请求
	request<T>(config: AxiosRequestConfig): Promise<T> {
		return new Promise((resolve, reject) => {
			this.instance
				.request<any, T>(config)
				.then(res => resolve(res))
				.catch(err => reject(err));
		});
	}

	// 封装请求方法
	get<T>(url: string, params?: object): Promise<T> {
		return this.request<T>({ url, params, method: 'GET' });
	}
	post<T>(url: string, data?: object): Promise<T> {
		return this.request<T>({ url, data, method: 'POST' });
	}
	delete<T>(url: string, data?: object): Promise<T> {
		return this.request<T>({ url, data, method: 'DELETE' });
	}
	patch<T>(url: string, data?: object): Promise<T> {
		return this.request<T>({ url, data, method: 'PATCH' });
	}
	special<T>(params: AxiosRequestConfig): Promise<T> {
		return this.request<T>(params);
	}
}

export default request;
